package com.zeng.sboot.redis.demo.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.support.collections.RedisCollectionFactoryBean;

import java.lang.reflect.Method;

/**
 * 第二种写法
 *
 * 如果需要自定义key的话,需要继承CachingConfigurerSupport类，并重写方法keyGenerator()
 *
 * */
//@Configuration
//@EnableCaching  //注解@EnableCaching开启缓存
public class RedisInitialize2 extends CachingConfigurerSupport {

    private static Logger logger = LoggerFactory.getLogger(RedisInitialize.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 采用RedisCacheManager作为缓存管理器
     *
     * 这里并没有显示注册 RedisConnectionFactory 是因为由 spring 默认读取到 application.properties
     * 配置文件并自动创建了 RedisConnectionFactory , 这里由spring在方法参数中注入并使用
     *
     * 也可以显示注册 RedisConnectionFactory , application.properties 中就不需要添加 redis 配置内容
     *
     *
     * 声明缓存管理器 RedisCacheManager , 会创建一个切面（aspect）并触发Spring缓存注解的切点（pointcut）
     * 根据类或者方法所使用的注解以及缓存的状态, 这个切面会从缓存中获取数据, 将数据添加到缓存之中或者从缓存中移除某个值
     * 在类方法上使用 @Cacheable("prudCache")
     * */
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory){
//        RedisCacheManager cacheManager = RedisCacheManager.create(redisConnectionFactory);
        RedisCacheManager cacheManager = new RedisCacheManager(stringRedisTemplate);
        return cacheManager;
    }


//    @Bean
//    public RedisTemplate redisTemplate(RedisConnectionFactory RedisConnectionFactory){
//        RedisTemplate<String, String> rt = new RedisTemplate<>();
//        rt.setConnectionFactory(RedisConnectionFactory);
//        return rt;
//    }

    /**
     * 自定义生成key的规则
     * 利用反射原理 读取类名+方法名+参数
     * */
    @Override
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            public Object generate(Object obj, Method method, Object... objs) {
                //格式化缓存key字符串
                StringBuilder sb = new StringBuilder();
                //追加类名
                sb.append(obj.getClass().getName());
                //追加方法名
                sb.append(".");
                sb.append(method.getName());
                //遍历参数并且追加
                for(Object o : objs){
                    sb.append(o.toString());
                }
                System.out.println("调用Redis缓存Key: " + sb.toString());
                logger.info("调用Redis缓存Key为 {}",sb.toString());
                return sb.toString();
            }
        };
    }

}